﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sheeps
{
    public class SuperGeniusDogBehavior : DogBehaviorAlogorithm
    {
        private Random randomizer;

        protected Vector3 GetRandomVector(double maxLength)
        {
            double randX = (randomizer.NextDouble() - 0.5) * 2; //-1 ; 1
            double randY = (randomizer.NextDouble() - 0.5) * 2;
            Vector3 randV = new Vector3(randX, randY, 0);
            randV.Normalize();
            randV *= maxLength * randomizer.NextDouble();

            return randV;
        }

        public override void UpdatePositions(GameState gameState)
        {            
            gameState.Dog.Position = GenerateDogMove(gameState);
        }

        public Vector3 GenerateDogMove(GameState gamestate)
        {
            MxSheepBehavior behav = new MxSheepBehavior();
            Vector3 currentBest = gamestate.Dog.Position, currentGenerationBest = gamestate.Dog.Position;

            double currentBestGrade=0;


            for (int i = 0; i < 4; i++)
            {
                double maxLength = gamestate.Dog.MaxMoveLength - (gamestate.Dog.Position - currentGenerationBest).Magnitude;
                for (int j = 0; j < 30; j++)
                {
                    GameState tmpGs = (GameState)gamestate.Clone();
                    Vector3 randV = this.GetRandomVector(maxLength);
                    Console.WriteLine("Randv: {0}", randV);
                    tmpGs.Dog.Position = currentGenerationBest + randV;
                    behav.UpdatePositions(tmpGs);
                    double grade = this.RatePosition(tmpGs, gamestate.CountSheepInPen());

                    if (grade >= currentBestGrade)
                    {
                        currentBest = currentGenerationBest + randV;
                        currentBestGrade = grade;
                    }
                }
                currentGenerationBest = currentBest;
            }

            Console.WriteLine("Current best v:\t" + currentBest);
            Console.WriteLine("Current best grade:\t" + currentBestGrade);
            return currentBest;
        }

        public double RatePosition(GameState virtualGameState, int SheepInPen)
        {
            double grade = 0, distanceToSheep = 100000, sheepAverage = 0;
            double angle=0;

            if (virtualGameState.CountSheepInPen() < SheepInPen)
                return 1000000 * (SheepInPen - virtualGameState.CountSheepInPen());

            var sortedSheep = (from sheep in virtualGameState.SheepList
                                 orderby (sheep.Position - virtualGameState.Dog.Position).Magnitude
                                 where !virtualGameState.IsSheepInPen(sheep)
                                 select sheep);
            
            Sheep closestSheep = sortedSheep.FirstOrDefault();
            if (closestSheep == null)
            {
                return 0;
            }

            foreach (var sh in virtualGameState.SheepList)
            {




                sheepAverage += (sh.Position - virtualGameState.PenCenter).Magnitude;
            }
            sheepAverage /= virtualGameState.SheepList.Count;

            distanceToSheep = (closestSheep.Position - virtualGameState.Dog.Position).Magnitude;
            if (distanceToSheep < 10)
               distanceToSheep = 500;

            Vector3 centreDog = virtualGameState.PenCenter - virtualGameState.Dog.Position;
            Vector3 centreSheep = virtualGameState.PenCenter - closestSheep.Position;

            angle = centreDog.Angle(centreSheep);
            if (centreDog.Magnitude < centreSheep.Magnitude)
            {
                angle /= 0.000000001*((centreDog.Magnitude / centreSheep.Magnitude) * (centreDog.Magnitude / centreSheep.Magnitude));
            }
 

            grade = 1 / distanceToSheep + 1/(7000*(angle+0.0000001))+ 5000 / sheepAverage;


            return grade;
        }

        public SuperGeniusDogBehavior()
        {
            this.randomizer = new Random();
        }

    }
}
